package depthtag;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.GregorianCalendar;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TimeZone;
import java.util.TreeMap;
import java.util.TreeSet;

import depthtag.display.Viewer;
import depthtag.filter.ZXUFilter;

public class LogParser {

	private static final String START_DATE_PREFIX = "ZDH";
	private Map<String, Double> timestamps = new TreeMap<String, Double>();
	SimpleDateFormat formater = new SimpleDateFormat("yyyy:MM:dd HH:mm:ss");
	SimpleDateFormat ZDHformaterMinutes = new SimpleDateFormat("yyyyMMddHHmm");
	SimpleDateFormat ZDHformaterSeconds = new SimpleDateFormat("yyyyMMddHHmmss");
	Set<String> addedLog = new TreeSet<String>();
	private int secondsDiffLogVsCamera = 0;

	public LogParser() {
		ZDHformaterMinutes.setTimeZone(TimeZone.getTimeZone("GMT-0"));
		ZDHformaterSeconds.setTimeZone(TimeZone.getTimeZone("GMT-0"));
		formater.setTimeZone(TimeZone.getTimeZone("GMT-0"));
	}

	public LogParser(int secondsDiffLogVsCamera) {
		this();
		this.secondsDiffLogVsCamera = secondsDiffLogVsCamera;
	}

	public Map<String, Double> getTimeStamps() {
		return timestamps;
	}

	public Map<String, Double> getContents(File aFile, Viewer viewer) {
		try {
			// use buffering, reading one line at a time
			// FileReader always assumes default encoding is OK!
			BufferedReader input = new BufferedReader(new FileReader(aFile));

			try {
				String line = null; // not declared within while loop
				Calendar timeStamp = null;
				List<String[]> tempList = new ArrayList<String[]>();
				/*
				 * readLine is a bit quirky : it returns the content of a line
				 * MINUS the newline. it returns null only for the END of the
				 * stream. it returns an empty String if two newlines appear in
				 * a row.
				 */
				while ((line = input.readLine()) != null) {
					if (line.startsWith(START_DATE_PREFIX)) {
						// ZDH|13|2 |I|Q20S|200912111221 |28|0||||
						// ZDH|1 |408|I|Q4S |20100130140133|22|16|FO2||0|
						String[] split = line.split("\\|");

						String dateString = split[5];
						timeStamp = new GregorianCalendar(TimeZone
								.getTimeZone("GMT-0"));
						timeStamp
								.setTime((dateString.length() == 12) ? ZDHformaterMinutes
										.parse(dateString)
										: ZDHformaterSeconds.parse(dateString));
						timeStamp.add(Calendar.SECOND, secondsDiffLogVsCamera);
						viewer.addStatusText("Adding dive starting at " + formater.format(timeStamp.getTime()));
						addedLog.add(formater.format(timeStamp.getTime()));
						// System.out.println("Adding " +
						// formater.format(timeStamp.getTime()));
					} else if (line.startsWith("|")) {
						/**
						 * |0|1.9|1|||| |0.07|2.24||||| |0.13|2.36|||||
						 * |0.2|2.58||||| |0.27|3.04||||| |0.33|3.48|||||
						 * |0.4|3.68||||| |0.47|3.76||||| |0.53|3.92|||||
						 * |0.6|4.04||||| |0.67|4.28||||| |0.73|4.44|||||
						 * |0.8|4.52||||| |0.87|4.64||||| |0.93|4.7|||||
						 * |1|4.84|||||
						 */
						String[] timeDepth = line.split("\\|");
						tempList.add(new String[] { timeDepth[2], timeDepth[1] });
					} else if (line.startsWith("ZDP}")) {
						// dive done

						int nrOfReadings = tempList.size();
						nrOfReadings--;
						float lastReadingTime = Float.parseFloat(tempList
								.get((nrOfReadings))[1]);
						float nrOfSecondsOfLogs = lastReadingTime * 60;
						int incrementsSecondsForEachReading = Math
								.round(nrOfSecondsOfLogs / nrOfReadings);

						float previousDepth = 0f;

						for (String[] timeDepth : tempList) {
							float currentDepth = Float.parseFloat(timeDepth[0]);
							float currentFractionOfMinute = Float
									.parseFloat(timeDepth[1]);

							float deltaDepth = currentDepth - previousDepth;
							float depthSteps = deltaDepth
									/ incrementsSecondsForEachReading;
							if (currentFractionOfMinute != 0) {
								;
								for (int i = 0; i < incrementsSecondsForEachReading; i++) {
									String timeToAdd = formater.format(timeStamp.getTime());
									Double depthToAdd = Double.valueOf(previousDepth + (depthSteps * i));
									timestamps.put(timeToAdd, depthToAdd);
									// System.out.println("timeToAdd= "+
									// timeToAdd + " depth=" + depthToAdd +
									// " currentDepth=" + currentDepth +
									// " previousDepth=" + previousDepth);
									timeStamp.add(GregorianCalendar.SECOND, (1));

								}
							}
							previousDepth = currentDepth;

						}
						// one last final time
						// buffer on one extra minute with last readings depth
						Double depthToAdd = Double.parseDouble(tempList.get(nrOfReadings)[0]);
						for (int i = 0; i < 60; i++) {
							String timeToAdd = formater.format(timeStamp
									.getTime());
							timestamps.put(timeToAdd, depthToAdd);
							timeStamp.add(GregorianCalendar.SECOND, (1));
						}
						// System.out.println("timeToAdd= "+ timeToAdd +
						// " depth=" + depthToAdd );
						viewer.addStatusText("Dive ended at "
								+ formater.format(timeStamp.getTime()) + "\n");
						tempList.clear();
					}
				}
			} catch (ParseException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} finally {
				input.close();
			}
		} catch (IOException ex) {
			ex.printStackTrace();
		}
		viewer.setNrOfLogs(addedLog.size());
		return timestamps;
	}

	public void readFolder(String folder, Viewer viewer) {
		File rootFolder = new File(folder);
		if (rootFolder.isDirectory()) {
			File[] files = rootFolder.listFiles(new ZXUFilter());
			for (File file : files) {
				viewer.addStatusText("parsing log " + file.getAbsoluteFile());
				getContents(file, viewer);

			}
		}
	}

}
